package com.bugsnag.ohos;

import com.bugsnag.ohos.util.OhosLog;

import java.lang.Thread;
import java.lang.Thread.UncaughtExceptionHandler;

/**
 * Provides automatic notification hooks for unhandled exceptions.
 */
class ExceptionHandler implements UncaughtExceptionHandler {
    private static final String TAG = "ExceptionHandler";
    private static final String STRICT_MODE_TAB = "StrictMode";
    private static final String STRICT_MODE_KEY = "Violation";

    private final UncaughtExceptionHandler originalHandler;
    private final StrictModeHandler strictModeHandler = new StrictModeHandler();
    private final Client client;
    private final Logger logger;

    ExceptionHandler(Client client, Logger logger) {
        this.client = client;
        this.logger = logger;
        this.originalHandler = Thread.getDefaultUncaughtExceptionHandler();
    }

    void install() {
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    void uninstall() {
        Thread.setDefaultUncaughtExceptionHandler(originalHandler);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        // 异常捕获处
        OhosLog.i(TAG, "uncaughtException thread %s ; throwable:%s", thread.getName(), throwable.toString());

        if (client.getConfig().shouldDiscardError(throwable)) {
            OhosLog.i(TAG, "uncaughtException shouldDiscardError");
            return;
        }

        boolean strictModeThrowable = strictModeHandler.isStrictModeThrowable(throwable);
        OhosLog.i(TAG, "uncaughtException strictModeThrowable %s", strictModeThrowable);

        Metadata metadata = new Metadata();
        String violationDesc = null;

        if (strictModeThrowable) {
            violationDesc = strictModeHandler.getViolationDescription(throwable.getMessage());
            metadata = new Metadata();
            metadata.addMetadata(STRICT_MODE_TAB, STRICT_MODE_KEY, violationDesc);
        }

        String severityReason = strictModeThrowable
            ? SeverityReason.REASON_STRICT_MODE : SeverityReason.REASON_UNHANDLED_EXCEPTION;

        if (strictModeThrowable) { // writes to disk on main thread
            client.notifyUnhandledException(throwable,
                metadata, severityReason, violationDesc);
        } else {
            client.notifyUnhandledException(throwable,
                metadata, severityReason, null);
        }

        if (originalHandler != null) {
            originalHandler.uncaughtException(thread, throwable);
        } else {
            System.err.printf("Exception in thread \"%s\" ", thread.getName());
            logger.w("Exception", throwable);
        }
        OhosLog.i(TAG, "uncaughtException end");
    }
}
